import math

from com.sikong.geoTransform.constant import Constant
from com.sikong.geoTransform.utils import CRSutils

class GeoTransformer:
    __doc__ = '''
    该工具类用于国内常用的坐标系转换
    通常情况下各公司采用坐标系如下：
    以高德为代表---------> gcj02
    以百度为代表---------> bd09
    全球通用------------> wgs84
    '''

    @staticmethod
    def gcj02tobd09(gcj_lon: float, gcj_lat: float):
        """
        该方法用于将gcj02坐标系转为bd09坐标系

        :param gcj_lon: gcj02坐标系下的经度
        :param gcj_lat: gcj02坐标系下的纬度
        :return: 返回bd09坐标系的经纬度
        """
        z = math.sqrt(gcj_lon * gcj_lon + gcj_lat * gcj_lat) + 0.00002 * math.sin(gcj_lat * Constant.x_pi)
        theta = math.atan2(gcj_lat, gcj_lon) + 0.000003 * math.cos(gcj_lon * Constant.x_pi)
        bd_lon = z * math.cos(theta) + 0.0065
        bd_lat = z * math.sin(theta) + 0.006

        return [bd_lon, bd_lat]

    @staticmethod
    def bd09togcj02(bd_lon: float, bd_lat: float):
        """
        该方法用于将bd09坐标系转为gcj02坐标系

        :param bd_lon: bd09坐标系下的经度
        :param bd_lat: bd09坐标系下的纬度
        :return: 返回gcj02坐标系下的经纬度
        """
        x = (bd_lon - 0.0065)
        y = (bd_lat - 0.006)
        z = (math.sqrt(x * x + y * y)) - (0.00002 * math.sin(y * Constant.x_pi))
        theta = math.atan2(y, x) - 0.000003 * math.cos(x * Constant.x_pi)
        gcj_lon = z * math.cos(theta)
        gcj_lat = z * math.sin(theta)

        return [gcj_lon, gcj_lat]

    @staticmethod
    def gcj02towgs84(gcj_lon: float, gcj_lat: float):
        """
        该方法用于将gcj02坐标系转为wgs84坐标系

        :param gcj_lon: gcj02坐标系下的经度
        :param gcj_lat: gcj02坐标系下的纬度
        :return: wgs84坐标系下的经纬度
        """
        dlat = CRSutils.transformlat(gcj_lon - 105.0, gcj_lat - 35.0)
        dlng = CRSutils.transformlon(gcj_lon - 105.0, gcj_lat - 35.0)
        radlat = gcj_lat / 180.0 * Constant.pi
        magic = math.sin(radlat)
        magic = 1 - Constant.ee * magic * magic
        sqrtmagic = math.sqrt(magic)
        dlat = (dlat * 180.0) / ((Constant.a * (1 - Constant.ee)) / (magic * sqrtmagic) * Constant.pi)
        dlng = (dlng * 180.0) / (Constant.a / sqrtmagic * math.cos(radlat) * Constant.pi)
        mglat = gcj_lat + dlat
        mglng = gcj_lon + dlng
        return [gcj_lon * 2 - mglng, gcj_lat * 2 - mglat]

    @staticmethod
    def bd09towgs84(bd_lon: float, bd_lat: float):
        """
        该方法用于将bd09坐标系转为wgs84坐标系

        :param bd_lon: bd09坐标系下的经度
        :param bd_lat: bd09坐标系下的纬度
        :return: 返回wgs84坐标下的经纬度
        """
        doubles_gcj = GeoTransformer.bd09togcj02(bd_lon, bd_lat)
        doubles_wgs84 = GeoTransformer.gcj02towgs84(doubles_gcj[0], doubles_gcj[1])
        return doubles_wgs84
